home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Devices and Hardware / Display Manager / Play Video Sample / RequestVideo.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  27.6 KB  |  734 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        RequestVideo.c
  3.  
  4.     Contains:    RequestVideo demonstrates the usage of the Display Manager introduced
  5.                 with the PowerMacs and integrated into the system under System 7.5. With
  6.                 the RequestVideo sample code library, developers will be able to explore
  7.                 the Display Manager API by changing bit depth and screen resolution on
  8.                 multisync displays on built-in, NuBus, and PCI based video. Display Manager 1.0
  9.                 is built into the Systems included with the first PowerMacs up through System 7.5.
  10.                 Display Manager 2.0 is included with the release of the new PCI based PowerMacs,
  11.                 and will be included in post 7.5 System Software releases. 
  12.     
  13.                 It is a good idea to reset the screen(s) to the original setting before exit
  14.                 since the call to RVSetVideoAsScreenPrefs() may not do the right thing under
  15.                 Display Manager 1.0 with certain video drivers.
  16.     
  17.                 For information on the use of this sample code, please the documentation in the Read Me file
  18.  
  19.     Written by: Eric Anderson    
  20.  
  21.     Copyright:    Copyright © 1995-1999 by Apple Computer, Inc., All Rights Reserved.
  22.  
  23.                 You may incorporate this Apple sample source code into your program(s) without
  24.                 restriction. This Apple sample source code has been provided "AS IS" and the
  25.                 responsibility for its operation is yours. You are not permitted to redistribute
  26.                 this Apple sample source code as "Apple sample source code" after having made
  27.                 changes. If you're going to re-distribute the source, we require that you make
  28.                 it clear in the source that the code was descended from Apple sample source
  29.                 code, but that you've made changes.
  30.  
  31.     Change History (most recent first):
  32.                 7/15/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  33.                 1/28/97        ewa                Updated source for Metrowerks CodeWarrior 11
  34.                 6/27/96        dal                RVRequestVideoSetting() no longer requires Slot Manager DM 2.0 can be used.
  35.                 6/27/96        dal                Added check for Display Library before making DM 2.0 calls.
  36.                 5/31/95        ewa                Added RVGetCurrentVideoSetting and RVConfirmVideoRequest routines
  37.                                             to make it easy to revert back to where you came from and to give
  38.                                             the user a chance to confirm the new setting if the new mode was
  39.                                             valid (ie: the card supports it) but not safe (the monitor may not).
  40.                 5/24/95        ewa                Give the kAllValidModesBit requestFlags option for safe only or all
  41.                                             valid resolution timings.
  42.     
  43.                 
  44.  
  45. */
  46.  
  47. #include "RequestVideo.h"
  48.  
  49. // Internal includes
  50. #include <Dialogs.h>
  51. #include <ROMDefs.h>
  52. #include <Devices.h>
  53. #include <Errors.h>
  54. #include <Gestalt.h>
  55. #include <Memory.h>
  56. #include <Palettes.h>
  57. #include <Slots.h>
  58. #include <Displays.h>
  59. #include <ConditionalMacros.h>    //DL
  60. #include <CodeFragments.h>    //DL
  61.  
  62. #if 0
  63. //#include <StdIO.h>
  64. //#include <stdlib.h>
  65. #else
  66. #define abs(x) ( ( (x) < 0 ) ? -(x) : (x) )
  67. #endif
  68.  
  69. //--------------------------------------------------------------
  70. //
  71. // Internal defines, structs, typedefs, and routine declarations
  72. //
  73. //--------------------------------------------------------------
  74. #define        KMonoDev            0                        // false (handy definitions for gdDevType settings)
  75. #define        kColorDev            1                        // true
  76. #define        char_Enter            0x03                    // for our filter proc
  77. #define        char_Return            0x0D                    //
  78. #define        iRevertItem            1                        // User buttons
  79. #define        iConfirmItem        2                        //
  80. #define        kSecondsToConfirm    8                        // seconds before confirm dialog is taken down
  81. #define        rConfirmSwtchAlrt    2735                    // ID of alert dialog
  82.  
  83. struct DepthInfo {
  84.     VDSwitchInfoRec            depthSwitchInfo;            // This is the switch mode to choose this timing/depth
  85.     VPBlock                    depthVPBlock;                // VPBlock (including size, depth and format)
  86. };
  87. typedef struct DepthInfo DepthInfo;
  88.  
  89. struct ListIteratorDataRec {
  90.     VDTimingInfoRec            displayModeTimingInfo;        // Contains timing flags and such
  91.     unsigned long            depthBlockCount;            // How many depths available for a particular timing
  92.     DepthInfo                *depthBlocks;                // Array of DepthInfo
  93. };
  94. typedef struct ListIteratorDataRec ListIteratorDataRec;
  95.  
  96. void GetRequestTheDM1Way (        VideoRequestRecPtr requestRecPtr,
  97.                                 GDHandle walkDevice);
  98.  
  99. void GetRequestTheDM2Way (        VideoRequestRecPtr requestRecPtr,
  100.                                 GDHandle walkDevice,
  101.                                 DMDisplayModeListIteratorUPP myModeIteratorProc,
  102.                                 DMListIndexType theDisplayModeCount,
  103.                                 DMListType *theDisplayModeList);
  104.  
  105. pascal void ModeListIterator (    void *userData,
  106.                                 DMListIndexType itemIndex,
  107.                                 DMDisplayModeListEntryPtr displaymodeInfo);
  108.  
  109. Boolean FindBestMatch (            VideoRequestRecPtr requestRecPtr,
  110.                                 short bitDepth,
  111.                                 unsigned long horizontal,
  112.                                 unsigned long vertical);
  113.  
  114. void GravitateMonitors (void);
  115.  
  116. pascal Boolean ConfirmAlertFilter (DialogRef dlg, EventRecord *evt, short *itemHit);
  117.  
  118. //--------------------------------------------------------------
  119. //
  120. // Implementation of sample code
  121. //
  122. //--------------------------------------------------------------
  123. OSErr RVSetVideoRequest (VideoRequestRecPtr requestRecPtr)
  124. {
  125.     GDHandle        aMonitor;
  126.     Boolean            displayMgrPresent;
  127.     unsigned long    displayMgrVersion;
  128.     OSErr            err;
  129.     Boolean            isColor;
  130.     long            value = 0;
  131.  
  132.     Gestalt(gestaltDisplayMgrVers, (long*)&displayMgrVersion);
  133.     Gestalt(gestaltDisplayMgrAttr,&value);
  134.     displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
  135.     if (displayMgrPresent)
  136.     {
  137.         if (requestRecPtr->displayMode && requestRecPtr->depthMode)
  138.         {
  139.             if (requestRecPtr->availBitDepth == 1)    // Based on avail bit depth, 
  140.                 isColor = KMonoDev;                    // set the device to a mono device, or
  141.             else isColor = kColorDev;                // set the device to a color device
  142.             SetDeviceAttribute(requestRecPtr->screenDevice,gdDevType,isColor);        
  143.             
  144.             // see how many monitors we have, aMonitor will be nil if we have only one.
  145.             aMonitor = DMGetFirstScreenDevice (dmOnlyActiveDisplays);            // get the first guy
  146.             aMonitor = DMGetNextScreenDevice ( aMonitor, dmOnlyActiveDisplays );    // get the next guy
  147.             
  148.             if (nil == aMonitor || displayMgrVersion >= 0x00020000)
  149.             {
  150.                 // only call DMSetDisplayMode if we have one monitor or DM2.0 is installed
  151.                 // since DM1.0 does not automatically gravitate monitors and our gravitate code
  152.                 // is not implemented.
  153.                 err = DMSetDisplayMode(    requestRecPtr->screenDevice,    // GDevice
  154.                         requestRecPtr->displayMode,                        // DM1.0 uses this
  155.                         &requestRecPtr->depthMode,                        // DM1.0 uses this
  156.                         (unsigned long) &(requestRecPtr->switchInfo),    // DM2.0 uses this rather than displayMode/depthMode combo
  157.                         nil);
  158.                 if (noErr == err)
  159.                 {
  160.                     // Do the monitor gravitate here if we are using a version less than DM2.0
  161.                     if (displayMgrVersion < 0x00020000)
  162.                         GravitateMonitors ();
  163.                 }
  164.                 else if (kDMDriverNotDisplayMgrAwareErr == err)
  165.                 {
  166.                     // DM not supported by driver, so all we can do is set the bit depth
  167.                     err = SetDepth (requestRecPtr->screenDevice, requestRecPtr->depthMode, gdDevType, isColor);
  168.                 }
  169.             }
  170.             else
  171.             {
  172.                 // we have more than one monitor and DM1.0 is installed, so all we can do is set the bit depth
  173.                 err = SetDepth (requestRecPtr->screenDevice, requestRecPtr->depthMode, gdDevType, isColor);
  174.             }
  175.             
  176.             return (err);    // we did try to set the request
  177.         }
  178.     }
  179.     return (-1);    // return a generic error
  180. }
  181.  
  182. // This extern should be removed once this function is formally defined in Displays.h
  183. extern pascal OSErr DMUseScreenPrefs(Boolean usePrefs, Handle displayState)
  184.  THREEWORDINLINE(0x303C, 0x03EC, 0xABEB);
  185.  
  186. OSErr RVSetVideoAsScreenPrefs (void)
  187. {
  188.     Handle        displaystate;
  189.     Boolean        displayMgrPresent;
  190.     long        value = 0;
  191.  
  192.     Gestalt(gestaltDisplayMgrAttr,&value);
  193.     displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
  194.     if (displayMgrPresent)
  195.     {
  196.         DMBeginConfigureDisplays (&displaystate);    // Tell the world it is about to change
  197.         DMUseScreenPrefs (true, displaystate);        // Make the change
  198.         DMEndConfigureDisplays (displaystate);        // Tell the world the change is over
  199.         
  200.         return (noErr);    // we (maybe) set the world back to a known setting
  201.     }
  202.     return (-1);    // return a generic error
  203. }
  204.  
  205. OSErr RVGetCurrentVideoSetting (VideoRequestRecPtr requestRecPtr)
  206. {
  207.     unsigned long        displayMgrVersion;
  208.     OSErr                error = paramErr;
  209.     CntrlParam            pBlock;
  210.     VDSwitchInfoRec        switchInfo;
  211.     AuxDCEHandle        theDCE;
  212.     VDSwitchInfoRec        videoMode;        
  213.  
  214.     requestRecPtr->availBitDepth            = 0;    // init to default - you can do it if it is important to you
  215.     requestRecPtr->availHorizontal            = 0;
  216.     requestRecPtr->availVertical            = 0;
  217.     requestRecPtr->availFlags                = 0;
  218.     requestRecPtr->displayMode                = -1; 
  219.     requestRecPtr->depthMode                = -1;
  220.     requestRecPtr->switchInfo.csMode        = 0;
  221.     requestRecPtr->switchInfo.csData        = 0;
  222.     requestRecPtr->switchInfo.csPage        = 0;
  223.     requestRecPtr->switchInfo.csBaseAddr    = 0;
  224.     requestRecPtr->switchInfo.csReserved    = 0;
  225.     
  226.     Gestalt(gestaltDisplayMgrVers, (long*)&displayMgrVersion);
  227.     if (requestRecPtr->screenDevice)
  228.     {
  229. //DL -    must also make sure that Display Library is installed, otherwise
  230. //        calling DMGetDisplayMode() will branch to nil.
  231. //DL        if (displayMgrVersion >= 0x00020000)
  232. #if GENERATINGCFM
  233.         if (displayMgrVersion >= 0x00020000 && (Ptr) DMGetDisplayMode != (Ptr) kUnresolvedCFragSymbolAddress)
  234. #else
  235.         if (displayMgrVersion >= 0x00020000)
  236. #endif
  237.         {    // get the info the DM 2.0 way
  238.             error = DMGetDisplayMode(requestRecPtr->screenDevice, &switchInfo);
  239.             if (noErr == error)
  240.             {
  241.                 requestRecPtr->depthMode            = switchInfo.csMode;
  242.                 requestRecPtr->displayMode            = switchInfo.csData; 
  243.                 requestRecPtr->switchInfo.csMode    = switchInfo.csMode;
  244.                 requestRecPtr->switchInfo.csData    = switchInfo.csData;
  245.             }
  246.             return (error);    // we (maybe) set the world back to a known setting
  247.         }
  248.         else
  249.         {    // get the info the DM 1.0 way
  250.             videoMode.csMode = -1;        // init to bogus value
  251.             videoMode.csData = -1;        // init to bogus value            
  252.             pBlock.ioNamePtr = nil;
  253.             pBlock.ioCRefNum = (*(requestRecPtr->screenDevice))->gdRefNum;
  254.             pBlock.csCode = cscGetCurMode;
  255.             *(Ptr *)&pBlock.csParam[0] = (Ptr)&videoMode;
  256.                 
  257.             error = PBStatusSync((ParmBlkPtr )&pBlock);    // ask the driver first....since we trust it the most
  258.                 
  259.             if ( noErr == error && ((-1 == videoMode.csMode) || (-1 == videoMode.csData)) )
  260.                 error = statusErr;
  261.             
  262.             if (noErr != error)    // if the driver has no clue fill it videoMode by hand as a last resort
  263.             {    
  264.                 theDCE = (AuxDCEHandle)GetDCtlEntry((*(requestRecPtr->screenDevice))->gdRefNum);
  265.                 
  266.                 if( theDCE )
  267.                 {
  268.                     videoMode.csData = (unsigned char)(*theDCE)->dCtlSlotId; 
  269.                     videoMode.csMode = (*(requestRecPtr->screenDevice))->gdMode;
  270.                     error = noErr;
  271.                 }
  272.             }
  273.             if (noErr == error)    // Set our data
  274.             {
  275.                 requestRecPtr->displayMode            = videoMode.csData; 
  276.                 requestRecPtr->depthMode            = videoMode.csMode;
  277.                 requestRecPtr->switchInfo.csMode    = videoMode.csMode;
  278.                 requestRecPtr->switchInfo.csData    = videoMode.csData;
  279.             }
  280.             return (error);    // we (maybe) set the world back to a known setting
  281.         }
  282.     }
  283.     return (-1);
  284. }
  285.  
  286. pascal Boolean ConfirmAlertFilter(DialogRef theDialog, EventRecord *theEvent, short *itemHit)
  287. {
  288.     char charCode;
  289.     Boolean enterORreturn;
  290.     Boolean returnValue = false;
  291.     WindowRef dialogWindow = GetDialogWindow(theDialog);    //DL
  292.  
  293.     if (0 == GetWRefCon(dialogWindow))
  294.         SetWRefCon (dialogWindow,TickCount());
  295.     else
  296.     {
  297.         if (GetWRefCon(dialogWindow) + kSecondsToConfirm * 60 < TickCount())
  298.         {
  299.             returnValue = true;
  300.             theEvent->what = nullEvent;
  301.             *itemHit = 1;
  302.         }
  303.         else
  304.         {
  305.             if (theEvent->what == keyDown)
  306.             {
  307.                 charCode = (char)theEvent->message & charCodeMask;
  308.                 enterORreturn = (charCode == (char)char_Return) || (charCode == (char)char_Enter);
  309.                 if (enterORreturn)
  310.                 {
  311.                     theEvent->what = nullEvent;
  312.                     returnValue = true;
  313.                     *itemHit = iRevertItem;
  314.                     if (enterORreturn && (0 != (theEvent->modifiers & optionKey)))
  315.                     {
  316.                         *itemHit = iConfirmItem;
  317.                     }
  318.                 }
  319.             }
  320.         }
  321.     }
  322.     return (returnValue);
  323. }
  324.  
  325. OSErr RVConfirmVideoRequest (VideoRequestRecPtr requestRecPtr)
  326. {
  327.     short            alertReturn;        // Alert() return value
  328.     ModalFilterUPP    confirmFilterUPP;    // got to have us one of them new fangled UPP thingies
  329.     
  330.     if (requestRecPtr->availFlags & 1<<kModeValidNotSafeBit)
  331.     {    // new mode is valid but not safe, so ask user to confirm
  332.         SetCursor(&qd.arrow);                                        // have to show the arrow
  333.  
  334.         confirmFilterUPP = NewModalFilterProc (ConfirmAlertFilter);    // create a new modal filter proc UPP
  335.         alertReturn = Alert(rConfirmSwtchAlrt, confirmFilterUPP);    // alert the user
  336.         DisposeRoutineDescriptor (confirmFilterUPP);                // of course there is no DisposeModalFilterProc...
  337.         
  338.         if (alertReturn != iConfirmItem)
  339.             return (-1);                            // tell the caller to switch back to a known setting
  340.         else return (noErr);                        // all is well with the new setting, just leave it
  341.     }
  342.     return (noErr);                                    // the mode was safe, so do nothing
  343. }
  344.  
  345.  
  346. OSErr RVRequestVideoSetting (VideoRequestRecPtr requestRecPtr)
  347. {
  348.     Boolean                            displayMgrPresent;
  349.     short                            iCount = 0;                    // just a counter of GDevices we have seen
  350.     DMDisplayModeListIteratorUPP    myModeIteratorProc = nil;    // for DM2.0 searches
  351.     SpBlock                            spBlock;
  352.     Boolean                            suppliedGDevice;    
  353.     DisplayIDType                    theDisplayID;                // for DM2.0 searches
  354.     DMListIndexType                    theDisplayModeCount;        // for DM2.0 searches
  355.     DMListType                        theDisplayModeList;            // for DM2.0 searches
  356.     long                            value = 0;
  357.     GDHandle                        walkDevice = nil;            // for everybody
  358. //DL START Check for the presence of DM 2.0 before calling DMNewDisplayModeList() and DMDisposeList().
  359.     OSErr                            gestaltErr;
  360.     unsigned long                    displayMgrVersion;
  361.     Boolean                         hasDM2 = false;
  362.     Boolean                         hasSlotMgr = false;
  363.     
  364.     gestaltErr = Gestalt(gestaltDisplayMgrVers, (long*)&displayMgrVersion);
  365.     if (    gestaltErr == noErr &&
  366. #if GENERATINGCFM
  367.             (Ptr) DMNewDisplayModeList != (Ptr) kUnresolvedCFragSymbolAddress &&
  368.             (Ptr) DMDisposeList != (Ptr) kUnresolvedCFragSymbolAddress &&
  369. #endif
  370.             displayMgrVersion >= 0x00020000    )
  371.     {
  372.         hasDM2 = true;
  373.     }
  374. //DL END
  375.  
  376.     Gestalt(gestaltDisplayMgrAttr,&value);
  377.     displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
  378. //DL    displayMgrPresent=displayMgrPresent && (SVersion(&spBlock)==noErr);    // need slot manager
  379.     hasSlotMgr = (SVersion(&spBlock)==noErr);    //DL
  380.     displayMgrPresent=displayMgrPresent && (hasDM2 || hasSlotMgr);    //DL - need slot manager only if using DM 1.0.
  381.     if (displayMgrPresent)
  382.     {
  383.         // init the needed data before we start
  384.         if (requestRecPtr->screenDevice)                            // user wants a specifc device?
  385.         {
  386.             walkDevice = requestRecPtr->screenDevice;
  387.             suppliedGDevice = true;
  388.         }
  389.         else
  390.         {
  391.             walkDevice = DMGetFirstScreenDevice (dmOnlyActiveDisplays);            // for everybody
  392.             suppliedGDevice = false;
  393.         }
  394.         
  395.         myModeIteratorProc = NewDMDisplayModeListIteratorProc(ModeListIterator);    // for DM2.0 searches
  396.     
  397.         // Note that we are hosed if somebody changes the gdevice list behind our backs while we are iterating....
  398.         // ...now do the loop if we can start
  399.         if( walkDevice && myModeIteratorProc) do // start the search
  400.         {
  401.             iCount++;        // GDevice we are looking at (just a counter)
  402.             if( noErr == DMGetDisplayIDByGDevice( walkDevice, &theDisplayID, false ) )    // DM1.0 does not need this, but it fits in the loop
  403.             {
  404.                 theDisplayModeCount = 0;    // for DM2.0 searches
  405. //DL                if (noErr == DMNewDisplayModeList(theDisplayID, 0, 0, &theDisplayModeCount, &theDisplayModeList) )
  406.                 if (hasDM2 && noErr == DMNewDisplayModeList(theDisplayID, 0, 0, &theDisplayModeCount, &theDisplayModeList) )
  407.                 {
  408.                     // search NuBus & PCI the new kool way through Display Manager 2.0
  409.                     GetRequestTheDM2Way (requestRecPtr, walkDevice, myModeIteratorProc, theDisplayModeCount, &theDisplayModeList);
  410.                     DMDisposeList(theDisplayModeList);    // now toss the lists for this gdevice and go on to the next one
  411.                 }
  412. //DL                else
  413.                 else if (hasSlotMgr)    //DL
  414.                 {
  415.                     // search NuBus only the old disgusting way through the slot manager
  416.                     GetRequestTheDM1Way (requestRecPtr, walkDevice);
  417.                 }
  418.             }
  419.         } while ( !suppliedGDevice && nil != (walkDevice = DMGetNextScreenDevice ( walkDevice, dmOnlyActiveDisplays )) );    // go until no more gdevices
  420.         if( myModeIteratorProc )
  421.             DisposeRoutineDescriptor(myModeIteratorProc);
  422.         return (noErr);    // we were able to get the look for a match
  423.     }
  424.     return (-1);        // return a generic error
  425. }
  426.  
  427. void GetRequestTheDM1Way (VideoRequestRecPtr requestRecPtr, GDHandle walkDevice)
  428. {
  429.     AuxDCEHandle myAuxDCEHandle;
  430.     unsigned long    depthMode;
  431.     unsigned long    displayMode;
  432.     OSErr            error;
  433.     OSErr            errorEndOfTimings;
  434.     short            height;
  435.     short            jCount = 0;
  436.     Boolean            modeOk;
  437.     SpBlock            spAuxBlock;
  438.     SpBlock            spBlock;
  439.     unsigned long    switchFlags;
  440.     VPBlock            *vpData;
  441.     short            width;
  442.  
  443.     myAuxDCEHandle = (AuxDCEHandle) GetDCtlEntry((**walkDevice).gdRefNum);    
  444.     spBlock.spSlot = (**myAuxDCEHandle).dCtlSlot;
  445.     spBlock.spID = (**myAuxDCEHandle).dCtlSlotId;
  446.     spBlock.spExtDev = (**myAuxDCEHandle).dCtlExtDev;
  447.     spBlock.spHwDev = 0;                                // we are going to get this pup
  448.     spBlock.spParamData = 1<<foneslot;                    // this slot, enabled, and it better be here.
  449.     spBlock.spTBMask = 3;                                // don't have constants for this yet
  450.     errorEndOfTimings = SGetSRsrc(&spBlock);            // get the spDrvrHW so we know the ID of this puppy. This is important
  451.                                                         // since some video cards support more than one display, and the spDrvrHW
  452.                                                         // ID can, and will, be used to differentiate them.
  453.     
  454.     if ( noErr == errorEndOfTimings )
  455.     {
  456.         // reinit the param block for the SGetTypeSRsrc loop, keep the spDrvrHW we just got
  457.         spBlock.spID = 0;                                // start at zero, 
  458.         spBlock.spTBMask = 2;                            // 0b0010 - ignore DrvrSW - why ignore the SW side? Is it not important for video?
  459.         spBlock.spParamData = (1<<fall) + (1<<foneslot) + (1<<fnext);    // 0b0111 - this slot, enabled or disabled, so we even get 640x399 on Blackbird
  460.         spBlock.spCategory=catDisplay;
  461.         spBlock.spCType=typeVideo;
  462.         errorEndOfTimings = SGetTypeSRsrc(&spBlock);    // but only on 7.0 systems, not a problem since we require DM1.0
  463.         
  464.         // now, loop through all the timings for this GDevice
  465.         if ( noErr == errorEndOfTimings ) do
  466.         {
  467.             // now, loop through all possible depth modes for this timing mode
  468.             displayMode = (unsigned char)spBlock.spID;    // "timing mode, ie:resource ref number"
  469.             for (jCount = firstVidMode; jCount<= sixthVidMode; jCount++)
  470.             {
  471.                 depthMode = jCount;        // vid mode
  472.                 error = DMCheckDisplayMode(walkDevice,displayMode,depthMode,&switchFlags,0,&modeOk);
  473.     
  474.                 // only if the mode is safe or we override it with the kAllValidModesBit request flag
  475.                 if (    noErr == error &&
  476.                         modeOk &&
  477.                         (    switchFlags & 1<<kNoSwitchConfirmBit ||
  478.                             requestRecPtr->requestFlags & 1<<kAllValidModesBit
  479.                         )
  480.                     )
  481.                 {
  482.                     // have a good displayMode/depthMode combo - now lets look inside
  483.                     spAuxBlock = spBlock;                // don't ruin the iteration spBlock!!
  484.                     spAuxBlock.spID = depthMode;        // vid mode
  485.                     error=SFindStruct(&spAuxBlock);        // get back a new spsPointer
  486.                     if (noErr == error)                    // keep going if no error…
  487.                     {
  488.                         spAuxBlock.spID = 0x01;            // mVidParams request
  489.                         error=SGetBlock (&spAuxBlock);    // use the new spPointer and get back...a NewPtr'ed spResult
  490.                         if (noErr == error)                // …keep going if no error…
  491.                         {                                // We have data! lets have a look
  492.                             vpData = (VPBlock*)spAuxBlock.spResult;
  493.                             height = vpData->vpBounds.bottom;    // left and top are usually zero
  494.                             width = vpData->vpBounds.right;
  495.                             
  496.                             if (FindBestMatch (requestRecPtr, vpData->vpPixelSize, vpData->vpBounds.right, vpData->vpBounds.bottom))
  497.                             {
  498.                                 requestRecPtr->screenDevice = walkDevice;
  499.                                 requestRecPtr->availBitDepth = vpData->vpPixelSize;
  500.                                 requestRecPtr->availHorizontal = vpData->vpBounds.right;
  501.                                 requestRecPtr->availVertical = vpData->vpBounds.bottom;
  502.                                 requestRecPtr->displayMode = displayMode;
  503.                                 requestRecPtr->depthMode = depthMode;
  504.                                 requestRecPtr->switchInfo.csMode = depthMode;                // fill in for completeness
  505.                                 requestRecPtr->switchInfo.csData = displayMode;
  506.                                 requestRecPtr->switchInfo.csPage = 0;
  507.                                 requestRecPtr->switchInfo.csBaseAddr = 0;
  508.                                 requestRecPtr->switchInfo.csReserved = 0;
  509.                                 if (switchFlags & 1<<kNoSwitchConfirmBit)
  510.                                     requestRecPtr->availFlags = 0;                            // mode safe
  511.                                 else requestRecPtr->availFlags = 1<<kModeValidNotSafeBit;    // mode valid but not safe, requires user validation of mode switch
  512.                             }
  513.  
  514.                             if (spAuxBlock.spResult) DisposePtr ((Ptr)spAuxBlock.spResult);    // toss this puppy when done
  515.                         }
  516.                     }
  517.                 }
  518.             }
  519.             // go around again, looking for timing modes for this GDevice
  520.             spBlock.spTBMask = 2;        // ignore DrvrSW
  521.             spBlock.spParamData =  (1<<fall) + (1<<foneslot) + (1<<fnext);    // next resource, this slot, whether enabled or disabled
  522.             errorEndOfTimings = SGetTypeSRsrc(&spBlock);    // and get the next timing mode
  523.         } while ( noErr == errorEndOfTimings );    // until the end of this GDevice
  524.     }
  525.  
  526. }
  527.  
  528. pascal void ModeListIterator(void *userData, DMListIndexType, DMDisplayModeListEntryPtr displaymodeInfo)
  529. {
  530.     unsigned long            depthCount;
  531.     short                    iCount;
  532.     ListIteratorDataRec        *myIterateData        = (ListIteratorDataRec*) userData;
  533.     DepthInfo                *myDepthInfo;
  534.     
  535.     // set user data in a round about way
  536.     myIterateData->displayModeTimingInfo        = *displaymodeInfo->displayModeTimingInfo;
  537.     
  538.     // now get the DMDepthInfo info into memory we own
  539.     depthCount = displaymodeInfo->displayModeDepthBlockInfo->depthBlockCount;
  540.     myDepthInfo = (DepthInfo*)NewPtrClear(depthCount * sizeof(DepthInfo));
  541.  
  542.     // set the info for the caller
  543.     myIterateData->depthBlockCount = depthCount;
  544.     myIterateData->depthBlocks = myDepthInfo;
  545.  
  546.     // and fill out all the entries
  547.     if (depthCount) for (iCount=0; iCount < depthCount; iCount++)
  548.     {
  549.         myDepthInfo[iCount].depthSwitchInfo = 
  550.             *displaymodeInfo->displayModeDepthBlockInfo->depthVPBlock[iCount].depthSwitchInfo;
  551.         myDepthInfo[iCount].depthVPBlock = 
  552.             *displaymodeInfo->displayModeDepthBlockInfo->depthVPBlock[iCount].depthVPBlock;
  553.     }
  554. }
  555.  
  556. void GetRequestTheDM2Way (    VideoRequestRecPtr requestRecPtr,
  557.                             GDHandle walkDevice,
  558.                             DMDisplayModeListIteratorUPP myModeIteratorProc,
  559.                             DMListIndexType theDisplayModeCount,
  560.                             DMListType *theDisplayModeList)
  561. {
  562.     short                    jCount;
  563.     short                    kCount;
  564.     ListIteratorDataRec        searchData;
  565.  
  566.     searchData.depthBlocks = nil;
  567.     // get the mode lists for this GDevice
  568.     for (jCount=0; jCount<theDisplayModeCount; jCount++)        // get info on all the resolution timings
  569.     {
  570.         DMGetIndexedDisplayModeFromList(*theDisplayModeList, jCount, 0, myModeIteratorProc, &searchData);
  571.         
  572.         // for all the depths for this resolution timing (mode)...
  573.         if (searchData.depthBlockCount) for (kCount = 0; kCount < searchData.depthBlockCount; kCount++)
  574.         {
  575.             // only if the mode is valid and is safe or we override it with the kAllValidModesBit request flag
  576.             if    (    searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeValid && 
  577.                     (    searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeSafe ||
  578.                         requestRecPtr->requestFlags & 1<<kAllValidModesBit
  579.                     )
  580.                 )
  581.             {
  582.                 if (FindBestMatch (    requestRecPtr,
  583.                                     searchData.depthBlocks[kCount].depthVPBlock.vpPixelSize,
  584.                                     searchData.depthBlocks[kCount].depthVPBlock.vpBounds.right,
  585.                                     searchData.depthBlocks[kCount].depthVPBlock.vpBounds.bottom))
  586.                 {
  587.                     requestRecPtr->screenDevice = walkDevice;
  588.                     requestRecPtr->availBitDepth = searchData.depthBlocks[kCount].depthVPBlock.vpPixelSize;
  589.                     requestRecPtr->availHorizontal = searchData.depthBlocks[kCount].depthVPBlock.vpBounds.right;
  590.                     requestRecPtr->availVertical = searchData.depthBlocks[kCount].depthVPBlock.vpBounds.bottom;
  591.                     
  592.                     // now set the important info for DM to set the display
  593.                     requestRecPtr->depthMode = searchData.depthBlocks[kCount].depthSwitchInfo.csMode;
  594.                     requestRecPtr->displayMode = searchData.depthBlocks[kCount].depthSwitchInfo.csData;
  595.                     requestRecPtr->switchInfo = searchData.depthBlocks[kCount].depthSwitchInfo;
  596.                     if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeSafe)
  597.                         requestRecPtr->availFlags = 0;                            // mode safe
  598.                     else requestRecPtr->availFlags = 1<<kModeValidNotSafeBit;    // mode valid but not safe, requires user validation of mode switch
  599.     
  600.                 }
  601.             }
  602.  
  603.         }
  604.     
  605.         if (searchData.depthBlocks)
  606.         {
  607.             DisposePtr ((Ptr)searchData.depthBlocks);    // toss for this timing mode of this gdevice
  608.             searchData.depthBlocks = nil;                // init it just so we know
  609.         }
  610.     }
  611. }
  612.  
  613. Boolean FindBestMatch (VideoRequestRecPtr requestRecPtr, short bitDepth, unsigned long horizontal, unsigned long vertical)
  614. {
  615.     // •• do the big comparison ••
  616.     // first time only if    (no mode yet) and
  617.     //                        (bounds are greater/equal or kMaximizeRes not set) and
  618.     //                        (depth is less/equal or kShallowDepth not set) and
  619.     //                        (request match or kAbsoluteRequest not set)
  620.     if    (    nil == requestRecPtr->displayMode
  621.             &&
  622.             (    (horizontal >= requestRecPtr->reqHorizontal &&
  623.                 vertical >= requestRecPtr->reqVertical)
  624.                 ||                                                        
  625.                 !(requestRecPtr->requestFlags & 1<<kMaximizeResBit)    
  626.             )
  627.             &&
  628.             (    bitDepth <= requestRecPtr->reqBitDepth ||    
  629.                 !(requestRecPtr->requestFlags & 1<<kShallowDepthBit)        
  630.             )
  631.             &&
  632.             (    (horizontal == requestRecPtr->reqHorizontal &&    
  633.                 vertical == requestRecPtr->reqVertical &&
  634.                 bitDepth == requestRecPtr->reqBitDepth)
  635.                 ||
  636.                 !(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)    
  637.             )
  638.         )
  639.         {
  640.             // go ahead and set the new values
  641.             return (true);
  642.         }
  643.     else    // can we do better than last time?
  644.     {
  645.         // if    (kBitDepthPriority set and avail not equal req) and
  646.         //        ((depth is greater avail and depth is less/equal req) or kShallowDepth not set) and
  647.         //        (avail depth less reqested and new greater avail) or
  648.         //        (request match or kAbsoluteRequest not set)
  649.         if    (    (    requestRecPtr->requestFlags & 1<<kBitDepthPriorityBit && 
  650.                     requestRecPtr->availBitDepth != requestRecPtr->reqBitDepth
  651.                 )
  652.                 &&
  653.                 (    (    bitDepth > requestRecPtr->availBitDepth &&
  654.                         bitDepth <= requestRecPtr->reqBitDepth
  655.                     )
  656.                     ||
  657.                     !(requestRecPtr->requestFlags & 1<<kShallowDepthBit)    
  658.                 )
  659.                 &&
  660.                 (    requestRecPtr->availBitDepth < requestRecPtr->reqBitDepth &&
  661.                     bitDepth > requestRecPtr->availBitDepth    
  662.                 )
  663.                 &&
  664.                 (    (horizontal == requestRecPtr->reqHorizontal &&    
  665.                     vertical == requestRecPtr->reqVertical &&
  666.                     bitDepth == requestRecPtr->reqBitDepth)
  667.                     ||
  668.                     !(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)    
  669.                 )
  670.             )
  671.         {
  672.             // go ahead and set the new values
  673.             return (true);
  674.         }
  675.         else
  676.         {
  677.             // match resolution: minimize Δh & Δv
  678.             if    (    abs((requestRecPtr->reqHorizontal - horizontal)) <=
  679.                     abs((requestRecPtr->reqHorizontal - requestRecPtr->availHorizontal)) &&
  680.                     abs((requestRecPtr->reqVertical - vertical)) <=
  681.                     abs((requestRecPtr->reqVertical - requestRecPtr->availVertical))
  682.                 )
  683.             {
  684.                 // now we have a smaller or equal delta
  685.                 //    if (h or v greater/equal to request or kMaximizeRes not set) 
  686.                 if (    (horizontal >= requestRecPtr->reqHorizontal &&
  687.                         vertical >= requestRecPtr->reqVertical)
  688.                         ||
  689.                         !(requestRecPtr->requestFlags & 1<<kMaximizeResBit)
  690.                     )
  691.                 {
  692.                     // if    (depth is equal or kBitDepthPriority not set) and
  693.                     //        (depth is less/equal or kShallowDepth not set) and
  694.                     //        ([h or v not equal] or [avail depth less reqested and new greater avail] or depth equal avail) and
  695.                     //        (request match or kAbsoluteRequest not set)
  696.                     if    (    (    requestRecPtr->availBitDepth == bitDepth ||            
  697.                                 !(requestRecPtr->requestFlags & 1<<kBitDepthPriorityBit)
  698.                             )
  699.                             &&
  700.                             (    bitDepth <= requestRecPtr->reqBitDepth ||    
  701.                                 !(requestRecPtr->requestFlags & 1<<kShallowDepthBit)        
  702.                             )
  703.                             &&
  704.                             (    (requestRecPtr->availHorizontal != horizontal ||
  705.                                 requestRecPtr->availVertical != vertical)
  706.                                 ||
  707.                                 (requestRecPtr->availBitDepth < requestRecPtr->reqBitDepth &&
  708.                                 bitDepth > requestRecPtr->availBitDepth)
  709.                                 ||
  710.                                 (bitDepth == requestRecPtr->reqBitDepth)
  711.                             )
  712.                             &&
  713.                             (    (horizontal == requestRecPtr->reqHorizontal &&    
  714.                                 vertical == requestRecPtr->reqVertical &&
  715.                                 bitDepth == requestRecPtr->reqBitDepth)
  716.                                 ||
  717.                                 !(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)    
  718.                             )
  719.                         )
  720.                     {
  721.                         // go ahead and set the new values
  722.                         return (true);
  723.                     }
  724.                 }
  725.             }
  726.         }
  727.     }
  728.     return (false);
  729. }
  730.  
  731. void GravitateMonitors (void)
  732. {
  733.     // do the magic gravitation here
  734. }